Deref coercions
型エラーが起きている時に、
自動的に.deref()が呼び出される
GPT-4.icon
Rustの参照解決型変換(Deref coercion)は、型が期待される場所で、自動的に参照を解除してターゲット型のメソッドや関数を呼び出す仕組みです。この機能を利用すると、Derefトレイトを実装している型が持つ参照先の型のメソッドや機能をそのまま使えます。
2. String と str の例
String型は可変な文字列を表し、 str(文字列スライス)のすべてのメソッドを利用できます。これは、StringがDeref<Target=str>を実装しているためです。
code:rust
fn main() {
let s = String::from("hello world");
// Stringに対してstrのメソッドsplit_atを直接呼び出す
let (first, second) = s.split_at(5);
println!("First: '{}', Second: '{}'", first, second);
// 出力: First: 'hello', Second: ' world'
}
StringはDeref<Target=str>を実装しているため、s.split_at(5)は自動的に&String → &strに変換されます。
strのすべてのメソッド(例: split_at, findなど)はStringでもそのまま利用可能です。
sは、&StringじゃなくてStringなのに、なぜDerefが使えるの?mrsekut.icon
GPT-4.icon
メソッド呼び出し時の特殊な挙動
Rustには「オブジェクト安全なメソッド呼び出しの糖衣構文」があり、メソッド呼び出し時に以下の手順が自動的に行われます:
値が参照される(借用される)
値(String型)がそのままではメソッドの型に合わない場合、自動的に参照(&Stringや&mut String)が作られます。
Derefが適用される
借用された型がDerefを実装している場合、Derefを使ってターゲット型(strなど)に変換されます。
ターゲット型のメソッドが呼び出される
最終的にターゲット型(この場合はstr)のメソッドが実行されます。
まじか、めっちゃ連鎖するやんmrsekut.icon
3. Vec<u8> と &[u8] の例
Vec<T>は動的配列を表します。Vec<u8>(バイトの配列)はDeref<Target=[T]>を実装しているため、&Vec<u8>は自動的に&[u8](バイトスライス)に変換されます。
code:rust
fn process_bytes(slice: &u8) { println!("Processing bytes: {:?}", slice);
}
fn main() {
// Vec<u8>を受け取り、&u8が必要な関数に渡す process_bytes(&v);
// 手動でデリファレンスしても同じ結果
process_bytes(&*v);
}
Vec<u8>はDeref<Target=[u8]>を実装しているため、&Vec<u8> → &[u8]の変換が自動的に行われます。
手動でデリファレンスしても同じ結果ですが、参照解決型変換により簡潔に記述できます。
---
4. 連続した参照解決の例
Rustでは参照解決型変換を連続して適用できます。たとえば、Rc<String>に対してstrのメソッドを直接呼び出す場合、次のような変換が連続して行われます:
&Rc<String> → &String → &str
code:rust
use std::rc::Rc;
fn main() {
let r = Rc::new(String::from("hello world"));
// Rc<String>に対してsplit_atを直接呼び出す
let (first, second) = r.split_at(5);
println!("First: '{}', Second: '{}'", first, second);
// 出力: First: 'hello', Second: ' world'
}
r.split_at(5)では次の変換が自動的に行われます:
1. &Rc<String> → &String(Rc<T>のDerefによる)
2. &String → &str(StringのDerefによる)
strのメソッドsplit_atを直接Rc<String>に対して呼び出せるようになります。